package nbcp.base.utils

import nbcp.base.extend.HasValue
import nbcp.base.extend.Unwind
import org.dom4j.DocumentHelper
import org.dom4j.Element
import org.dom4j.Node
import org.dom4j.QName
import java.util.*
import java.util.stream.Collectors

/**
 * @author Yuxh
 */
object XmlUtil {
    /**
     * 按NodeName路径查询节点， 忽略 nammespace。 如果以双斜线开头， 是从任意节点查找；否则从目标节点根节点开始找。
     *
     * @param doc ,  var doc = new SAXReader().read(pomFile); var parentDoc = getParentPomDoc(doc);
     * @param tags
     */
    fun getElements(doc: Node, vararg tags: String): List<Element> {
        return doc.selectNodes(getXPath(*tags))
            .map { it as Element }
    }

    /**
     * 按NodeName路径查询节点， 忽略 nammespace。 如果以双斜线开头， 是从任意节点查找；否则从目标节点根节点开始找。
     *
     * @param doc
     * @param tags
     * @return
     */
    fun getSingleElement(doc: Node, vararg tags: String): Element? {
        return doc.selectSingleNode(getXPath(*tags)) as Element?
    }

    /**
     * 根据每个tag，返回 xpath
     *
     * @param tags
     * @return
     */
    private fun getXPath(vararg tags: String): String {
        val tags2 = tags
            .map { it.split("\\/".toRegex()).dropLastWhile { it.isEmpty() } }

        // project/*[name()='parent']/*[name()='version']
        var xPath = tags2.Unwind()
            .filter { it.HasValue }
            .map {
                val attrIndex = it.indexOf('[')
                if (attrIndex < 0) {
                    return@map "*[name()='$it']"
                } else if (attrIndex == 0) {
                    return@map "*$it"
                }
                val tag = it.substring(0, attrIndex)
                "*[name()='" + tag + "']" + it.substring(attrIndex)
            }
            .joinToString("/")

        val isAnyPath = tags[0].startsWith("//")
        if (isAnyPath) {
            xPath = "//$xPath"
        }
        return xPath
    }

    /**
     * 创建一个 同名称空间的元素。没有 xmlns
     *
     * @param anyNode
     * @return
     */
    fun createElement(tag: String, anyNode: Node): Element {
        return DocumentHelper.createElement(QName.get(tag, anyNode.document.rootElement.namespace))
    }

    /**
     * 移除元素
     *
     * @param element
     * @return
     */
    fun removeFromParent(element: Node): Boolean {
        return element.parent.remove(element)
    }
}
